<?php

namespace app\admin\command;

use think\console\input\Argument;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use think\Log;

class Hnt extends Command
{
    /*** @var float $average 矿机产币比例 */
    protected $average;

    /*** @var float $company_hnt 沉淀到公司的币 */
    protected $company_hnt = 0.00;

    /*** @var array $user_list 用户数据 */
    protected $user_list = [];

    /*** @var array $save_user_list 更新的用户数据 */
    protected $save_user_list = [];

    /*** @var array $user_hnt_log 分币记录 */
    protected $user_hnt_log = [];

    /*** @var float $user_rate 用户直属机器分币率 */
    protected $user_rate = 0.8;

    /*** @var float $company_rate 公司所得机器分币率 */
    protected $company_rate = 0.2;

    /*** @var float $branch_rate 身份分币比率基数 */
    protected $branch_rate = 0.25;

    /*** @var float $manager_rate 经理分币率 */
    protected $manager_rate = 0.6;

    /*** @var float $inspector_accumulation_rate 总监分币率 */
    protected $inspector_accumulation_rate = 0.4;

    /*** @var float $company_money_before 公司更新之前的金额 */
    protected $company_money_before;

    protected function configure()
    {
        $this->setName('hnt')->setDescription('分币')
            ->addArgument('average', Argument::OPTIONAL, "平均值", 0);
    }

    protected function execute(Input $input, Output $output)
    {
        $this->average = $input->getArgument('average');

        if (!is_float((float)$this->average)) {
            $this->average = '0.00';
        } else {
            $this->getAverage();
        }

        $this->start();
    }

    protected function start()
    {
        Db::startTrans();
        try {
            $this->user_list = \app\common\model\User::where('distribution_id', '<>', -1)->field("id,username,pid,IFNULL(pids,'') pids,distribution_id,HNT")->order('id desc')->select();

            foreach ($this->user_list as $item) {
                if ($item->id == 1 || empty($item->pids)) {
                    $this->company_money_before = $item->HNT;
                    continue;
                }

                // 最近经理
                $manager = \app\common\model\User::where(['id' => ['in', $item->pids], 'distribution_id' => 5])->field("id,pid,IFNULL(pids,'') pids,distribution_id,HNT")->order('id desc')->find();

                // 最近总监
                $inspector = \app\common\model\User::where(['id' => ['in', $item->pids], 'distribution_id' => 4])->field("id,pid,IFNULL(pids,'') pids,distribution_id,HNT")->order('id desc')->find();

                $manager_id = $inspector_id = 0;
                if (!is_null($manager)) {
                    $manager_id = $manager->id;
                }

                if (!is_null($inspector)) {
                    $inspector_id = $inspector->id;
                }

                // 会员机器数
                list($user_total_num, $user_up_num) = $this->getUserMachineNum($item->id);

                // 根据评价值获取机器产币量 当前用户产币量
                $this->calcSelfHNT($user_total_num, $item->id);

                // 不可分币的公司20%
                $company_definitely_output = bcmul($user_total_num, $this->average, 2);
                $company_definitely = bcmul($company_definitely_output, $this->company_rate, 2);

                // 公司共得
                $this->company_hnt = bcadd($this->company_hnt, $company_definitely, 2);

                // 开始分币
                $manager_output = bcmul($user_total_num, $this->average, 2);

                // 公司20% 默认15% + 给经理/总监 出去的 超过23台的部分5% 之后的部分 最后存储
                $company_output = bcmul($manager_output, $this->company_rate, 2);

                // 可分的
                $allow_hnt = bcmul($company_output, $this->branch_rate, 2);

                // 普通用户
                if ($item->distribution_id >= 0) {
                    $is_top = true;

                    // 用户->经理
                    if ($manager_id > 0) {
                        $is_top = false;

                        // 经理分币
                        $this->getUserHNT($manager_id, $allow_hnt, $this->manager_rate, $item, "业务经理");
                    }

                    // 用户->总监
                    if ($inspector_id > 0) {

                        // 用户->总监 直接分
                        $this->getUserHNT($inspector_id, $allow_hnt, $is_top ? 1 : $this->inspector_accumulation_rate, $item, "业务总监");
                    }
                }
            }

            // 公司用户
            list($hnt, $before, $after) = $this->userCurrency(1, $this->company_hnt, "公司用户");
            $this->user_hnt_log[] = ['user_id' => 1, 'HNT' => $hnt, 'before' => $before, 'after' => $after, 'memo' => "公司沉淀分币" . $hnt . 'HNT'];

            model('app\common\model\User')->saveAll($this->save_user_list);
            model('app\common\model\HNTLog')->saveAll($this->user_hnt_log);

            Db::commit();
        } catch (\Exception $exception) {
            Db::rollback();

            $tip = $exception->getMessage() . ' ' . $exception->getFile() . ' ' . $exception->getLine();
            Log::error("分币异常: $tip");
        }
    }

    /**
     * 获取用户当前 hnt
     * @param int $user_id 用户id
     * @param int $allow_hnt 总分币量
     * @param float|string $rate 当前身份比例
     * @param object $user 下级用户信息
     * @return array
     */
    protected function getUserHNT($user_id, $allow_hnt, $rate, $user, $tip)
    {
        // 经理
        $manager_hnt = bcmul($allow_hnt, $rate, 2);

        $current_hnt = 0.00;
        $after = 0.00;

        $not_found = true;
        foreach ($this->user_list as $item) {
            if ($item->id == $user_id) {
                if (array_key_exists($user_id, $this->save_user_list)) {
                    // 获取用户当前hnt数据
                    $current_hnt = $this->save_user_list[$user_id]['HNT'];
                    // 累计新hnt数据
                    $this->save_user_list[$user_id]['HNT'] = function_exists('bcadd') ? bcadd($current_hnt, $manager_hnt, 2) : $current_hnt + $manager_hnt;
                    $after = $this->save_user_list[$user_id]['HNT'];
                } else {
                    $current_hnt = $item->HNT;
                    $after = function_exists('bcadd') ? bcadd($current_hnt, $manager_hnt, 2) : $current_hnt + $manager_hnt;
                    $this->save_user_list[$user_id] = ['id' => $user_id, 'HNT' => $after];
                }
                $not_found = false;
                break;
            }
        }

        if ($not_found) {
            $manager_hnt = 0;
            Log::notice("用户 $user->id $user->username 未找到上级 $user_id 的信息");
        } else {
            // 公司的减去经理的 20-2
            $this->company_hnt = function_exists('bcsub') ? bcsub($this->company_hnt, $manager_hnt, 2) : $this->company_hnt - $manager_hnt;
            $this->user_hnt_log[] = ['user_id' => $user_id, 'HNT' => $manager_hnt, 'before' => $current_hnt, 'after' => $after, 'memo' => "{$tip}伞下用户" . $user->username . '提供分币' . $manager_hnt . 'HNT'];
        }
        return [$manager_hnt, $current_hnt, $after];
    }

    /**
     * 累加用户币
     * @param $user_id 用户id
     * @param $hnt 累加币
     * @return void
     */
    protected function userCurrency($user_id, $hnt, $memo = '')
    {
        $current_hnt = $after = 0.00;
        $not_found = true;
        foreach ($this->user_list as $item) {
            if ($item->id == $user_id) {
                $current_hnt = $item->HNT;
                $after = function_exists('bcadd') ? bcadd($current_hnt, $hnt, 2) : $current_hnt + $hnt;
                if (!array_key_exists($item->id, $this->save_user_list)) {
                    $this->save_user_list[$item->id] = ['id' => $item->id, 'HNT' => $after];
                } else {
                    $current_hnt = $this->save_user_list[$item->id]['HNT'];
                    $after = function_exists('bcadd') ? bcadd($current_hnt, $hnt, 2) : $current_hnt + $hnt;
                    $this->save_user_list[$item->id]['HNT'] = $after;
                }
                $not_found = false;
                break;
            }
        }

        // 当前 新增 之后
        if ($not_found) {
            Log::notice("找不到公司用户 $user_id 的信息 累加:$hnt 当前:$current_hnt 之后:$after");
        }
        return [$hnt, $current_hnt, $after];
    }

    /**
     * 平均数
     * @return string|null
     */
    protected function getAverage(): ?string
    {
        $total_machine = 10000; // 公司总机器
        $total_gold = 10000; // 总产币数
        return bcdiv($total_gold, $total_machine, 2);
    }

    /**
     * 用户设备数 和 用户可计算分币设备数
     * @param int $user_id 用户id
     * @return int|string
     */
    protected function getUserMachineNum($user_id)
    {
        $up_num = 0;
        $total_num = \app\admin\model\Machine::where(['user_id' => $user_id, 'state' => 1])->count();
        return [$total_num, $up_num];
    }

    /**
     * 计算用户自己的币
     * 用户自己获取的币 用户所得80%, 公司得20%(5% 分币)
     * @param int $user_total_num 机器数
     * @param int $user_id 用户信息
     * @return void
     */
    protected function calcSelfHNT($user_total_num, $user_id)
    {
        $manager_output = bcmul($user_total_num, $this->average, 2);

        // 当前用户币值  会员机器 * 平均数 * 0.8
        $user_output = bcmul($manager_output, $this->user_rate, 2);
        list($hnt, $before, $after) = $this->userCurrency($user_id, $user_output, 'user self');
        $this->user_hnt_log[] = ['user_id' => $user_id, 'HNT' => $hnt, 'before' => $before, 'after' => $after, 'memo' => "所属机器提供收益" . $hnt . 'HNT'];
    }
}
